package com.compose.skia

import android.content.Context
import android.os.Handler
import android.os.HandlerThread
import android.os.Looper
import android.os.Message
import android.util.AttributeSet
import android.util.Log
import android.view.Surface
import android.view.SurfaceHolder
import android.view.SurfaceView
import androidx.lifecycle.DefaultLifecycleObserver
import androidx.lifecycle.LifecycleOwner
import com.compose.skia.CanvasLoader.render
import com.compose.utils.AssetsFileReader


class SkiaCanvasView @JvmOverloads constructor(context: Context?, attrs: AttributeSet? = null, defStyleAttr: Int = 0) :
    SurfaceView(context, attrs, defStyleAttr), SurfaceHolder.Callback2, DefaultLifecycleObserver {
    private var appJSFilePath: String?
    private var mHolder: SurfaceHolder? = null
    private var mHandlerThread: HandlerThread? = null
    private var mHandler: Handler? = null
    private lateinit var app: JSApp

    init {
        val typedArray = getContext().obtainStyledAttributes(attrs, com.compose.skia.skia.R.styleable.SkiaCanvasView)
        appJSFilePath = typedArray.getString(com.compose.skia.skia.R.styleable.SkiaCanvasView_app_file_path)
        typedArray.recycle();
        init()
    }

    private fun init() {
        mHandlerThread = HandlerThread("SkiaRenderThread")
        mHolder = holder
        mHolder?.addCallback(this)
        mHandlerThread!!.start()
        mHandler = SkiaHandler(mHandlerThread!!.looper)


        if (context is LifecycleOwner) {
            val lifecycleOwner = context as LifecycleOwner
            lifecycleOwner.lifecycle.addObserver(this)
        }
    }

    override fun surfaceRedrawNeeded(holder: SurfaceHolder) {
        Log.e("SkiaCanvasView", "surfaceRedrawNeeded: ")
//        app.onAttachSurface(holder.surface, width, height)
    }

    override fun surfaceCreated(holder: SurfaceHolder) {
        val message = Message()
        message.what = DRAW
        message.obj = holder.surface
        message.arg1 = width
        message.arg2 = height
        mHandler!!.sendMessage(message)
//        Log.e("create", "width:$width,height:$height")
        app.onAttachSurface(holder.surface, width, height)
    }

    override fun surfaceChanged(holder: SurfaceHolder, format: Int, width: Int, height: Int) {
        val message = Message()
        message.what = DRAW
        message.obj = holder.surface
        message.arg1 = width
        message.arg2 = height
        mHandler!!.sendMessage(message)
        app.onAttachSurface(holder.surface, width, height)
    }

    override fun surfaceDestroyed(holder: SurfaceHolder) {
        app.onDetachSurface(holder.surface)
    }

    override fun onDetachedFromWindow() {
        super.onDetachedFromWindow()
        mHandlerThread!!.quit()
    }

    private class SkiaHandler(looper: Looper?) : Handler(looper!!) {
        override fun handleMessage(msg: Message) {
            super.handleMessage(msg)
            if (msg.what == DRAW) {
                synchronized(SkiaCanvasView::class.java) {
                    render(msg.obj as Surface, msg.arg1, msg.arg2)
                }
            }
        }
    }

    override fun onCreate(owner: LifecycleOwner) {
        super.onCreate(owner)
        val jsCode = appJSFilePath?.run {
            AssetsFileReader.readFileFromAssets(context, appJSFilePath)
        }
        app = JSApp.createApp(jsCode)
        app.onStart()
    }

    override fun onResume(owner: LifecycleOwner) {
        super.onResume(owner)
        app.onResume()
    }

    override fun onPause(owner: LifecycleOwner) {
        super.onPause(owner)
        app.onPause()
    }

    override fun onDestroy(owner: LifecycleOwner) {
        super.onDestroy(owner)
        app.onDestroy()
    }

    companion object {
        private const val DRAW = 1
    }
}
